/**
  * Author: Mei
  * Date: 2020-12-08 20:25
  * Description: 
  * result_of<> 适用于类型
  * typename适用于具体的对象
  *
  */
#include <iostream>
#include <functional>

using namespace std;

template<typename Foo, typename Argv>
typename std::result_of<Foo(Argv)>::type invoke(Foo f, Argv a) {
    return f(a);
};

template<typename Foo, typename Argv>
auto invoke1(Foo f, Argv a) -> decltype(f(a)) {
    return f(a);
}

template<typename Foo, typename Argv>
auto invoke2(Foo f, Argv a) -> decltype(Foo()(a)) {
    return f(a);
}

template<typename Foo, typename...Args>
auto invoke3(Foo &&f, Args &&... args) -> decltype(f(args...)) {
    //函数的返回值类型
    using return_type = typename std::result_of<Foo(Args...)>::type;
    //可以直接将函数和参数绑定在一起 方便
    function<decltype(f(args...))()> func = bind(std::forward<Foo>(f), std::forward<Args>(args)...);
    return func();
}

template<typename Foo, typename type>
auto invoke4(Foo f, type a) -> decltype(f(a)) {
    function<decltype(f(a))(type)> func = bind(f, std::placeholders::_1, 20);
    return func(3);
}

int max1(int a, int b) {
    return a + b +
           1;
}

int max2(int a) {
    return a + 1;
}

typedef function<int(int)> f;

int main() {
    int n = 3;
    //f f1 = max1;
    //cout << f1(n) << endl;
    cout << invoke3(max1, n, 32) << endl;

    function<int(int)> func = bind(max1, std::placeholders::_1, 20);
    cout << func(20) << endl;
    //cout << invoke4(max1, 4) << endl;

    return 0;
}